﻿namespace Rsdn.Janus
{
    using System;
    using System.IO;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using Framework;
    using Framework.Ipc;
    using GoJanusNet;
    using Microsoft.Win32;
    using MultiLang;

    /// <summary>
    /// Вспомогательный COM объект для обработки пунктов контекстного меню IE.
    /// </summary>
    [ComVisible(true)]
    [Guid(ClsId)]
    [ProgId("Janus.GoUrl")]
    public class GoUrl : IGoUrl
    {
        #region Private members
        private const string _pipeName = "JanusPipe";                       //MLHIDE
        private const string _registryKeyPrefix = @"Software\Microsoft\Internet Explorer\MenuExt\"; //MLHIDE

        // не локализовывать ключи
        // текст записывается в реестр и после можно получить тексты на нескольких языках
        private static string _registryKeySendUrl =
            _registryKeyPrefix + "RSDN@Home: загрузить тему при след.синхр.";//MLHIDE

        private static string _registryKeyShowMessage =
            _registryKeyPrefix + "RSDN@Home: открыть сообщение в клиенте";//MLHIDE

        public const string ClsId = "61D7E14A-F91B-4db4-A97F-340218484E86"; //MLHIDE

        private static readonly object _filesCreateLock = new object();

        [Flags]
        private enum IEContext
        {
            Unknown = 0x00,
            //Default = 0x01,
            //Image = 0x02,
            //Control = 0x04,
            //Table = 0x08,
            //TextSelect = 0x10,
            Anchor = 0x20
        }
        #endregion

        #region IGoUrl Members
        public void SendURLToJanus(int messageID, string linkText)
        {
            if (string.IsNullOrEmpty(linkText))
                throw new ArgumentException("linkText");                          //MLHIDE

            WriteToPipe(string.Format(
                "<download-topic><message-id>{0}</message-id><hint>{1}</hint></download-topic>", //MLHIDE
                messageID, linkText));
        }

        public int DownloadURL(string linkText, string hintText)
        {
            int ret = -1;
            if (string.IsNullOrEmpty(linkText))
            {
                throw new ArgumentException("linkText"); // MLHIDE
            }

            if (SharedFunctions.StartJanus())
            {
                WriteToPipe(
                    string.Format(
                        "<download-topic><version>2</version><message-id>0</message-id><url>{0}</url><hint>{1}</hint></download-topic>", //MLHIDE
                        linkText, hintText));
                ret = 0;
            }

            return ret;
        }


        public int ShowURL(string linkText)
        {
            int ret = -1;
            if (string.IsNullOrEmpty(linkText))
            {
                throw new ArgumentException("linkText"); // MLHIDE
            }
            
            bool startJanus = SharedFunctions.StartJanus();
            
            if (startJanus)
            {
                WriteToPipe(
                    string.Format(
                        "<goto-message><version>2</version><message-id>0</message-id><url>{0}</url></goto-message>", //MLHIDE
                         linkText));
                ret = 0;
            }

            return ret;
        }

        public void ShowMessageInJanus(int messageID)
        {
            WriteToPipe(string.Format(
                "<goto-message><message-id>{0}</message-id></goto-message>",      //MLHIDE
                messageID));
        }
        #endregion

        #region Install / Uninstall
        // автоматический вызов функции
        [ComRegisterFunction]
        internal static void Install(Type t)
        {
            Console.WriteLine("Install GoJanusNet");                           //MLHIDE

            InstallIeContextMenuItem(_registryKeySendUrl, ".html", IEContext.Anchor); //MLHIDE
            InstallIeContextMenuItem(_registryKeyShowMessage, "_gm.html", IEContext.Anchor); //MLHIDE
        }

        [ComUnregisterFunction]
        internal static void Uninstall(Type t)
        {
            Console.WriteLine("Uninstall GoJanusNet");                         //MLHIDE
            try
            {
                Registry.CurrentUser.DeleteSubKeyTree(_registryKeySendUrl);
                Registry.CurrentUser.DeleteSubKeyTree(_registryKeyShowMessage);
            }
            catch (Exception ex)
            {
                // ignore any exceptions
            }
        }

        private static void InstallIeContextMenuItem(string registryKeyName, string suffix,
            IEContext contexts)
        {
            lock (_filesCreateLock)
            {
                try
                {
                    Assembly executingAssembly = Assembly.GetExecutingAssembly();
                    Stream resShowMessageStream = executingAssembly.GetManifestResourceStream(
                        "Rsdn.Janus." + typeof(GoUrl).Assembly.ManifestModule.Name + suffix); //MLHIDE
                    if (resShowMessageStream == null)
                    {
                        throw new ApplicationException(ml.ml_string(3, "Не удалось создать поток ресурса"));
                    }

                    const int copyBufSize = 8192;
                    byte[] buffer = new byte[copyBufSize];

                    using (FileStream fs = new FileStream(typeof(GoUrl).Assembly.Location + suffix, FileMode.Create))
                    {
                        int bytesRead;
                        while ((bytesRead = resShowMessageStream.Read(buffer, 0, copyBufSize)) != 0)
                        {
                            fs.Write(buffer, 0, bytesRead);
                        }
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }

            using (var rk = Registry.CurrentUser.CreateSubKey(registryKeyName))
            {
                if (rk == null)
                {
                    throw new ApplicationException(ml.ml_string(4, "Не удалось создать раздел реестра"));
                }

                rk.SetValue("", typeof (GoUrl).Assembly.CodeBase + suffix);
                if (contexts != IEContext.Unknown)
                {
                    rk.SetValue("contexts", (int) contexts); //MLHIDE
                }

                rk.SetValue(ClsId, "");
            }
        }
        #endregion

        private static void WriteToPipe(string str)
        {
            using (var cpc = new ClientPipeConnection(_pipeName))
                try
                {
                    cpc.Connect();
                    cpc.Write(str);
                }
                //{{{-EmptyGeneralCatchClause
                catch
                //{{{+EmptyGeneralCatchClause
                { }
        }


        //OPEN EVENT
        [DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
        private static extern IntPtr OpenEvent(UInt32 dwDesiredAccess, Boolean bInheritHandle, String lpName);


    }
}